package drytools.site.beans;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;

import javax.faces.component.UIViewRoot;
import javax.faces.context.FacesContext;
import javax.faces.event.AbortProcessingException;
import javax.faces.event.ActionEvent;
import javax.faces.event.ActionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;

import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.traversal.NodeFilter;
import org.xml.sax.SAXException;

import com.icesoft.faces.component.menubar.MenuItem;
import com.icesoft.faces.component.tree.IceUserObject;
import com.icesoft.faces.context.DOMContext;
import com.sun.org.apache.xerces.internal.dom.DocumentImpl;
import com.sun.org.apache.xerces.internal.dom.NodeIteratorImpl;
import com.sun.org.apache.xpath.internal.XPathAPI;

import drytools.site.css.CSSTools;
import drytools.site.model.AllElements;
import drytools.site.model.CSSStyleWrapper;
import drytools.site.model.CollectionSorter;
import drytools.site.model.ObjectWithTags;
import dryworks.jsf.examples.model.Example;
import dryworks.jsf.parsers.FacesConfigParser;
import dryworks.jsf.parsers.NodesNamesCollector;

public class ExamplesExplorerBean {

	String currentExampleShortName;
	private List<MenuItem> topMenuModel;
	private List<MenuItem> examplesExploderMenuModel;
	LinkedHashMap<String, ObjectWithTags<Example>> allExamplesMapByShortName = null;
	Map<String, DefaultTreeModel> topCategoriesTrees = null;
	LinkedHashMap<String, Object> currentExampleHierarhy = null;
	String userId;
	CSSTools cssTools;
	
	public String getUserId() {
		if (userId == null) {
			userId = "userId:"
					+ FacesContext.getCurrentInstance().getExternalContext()
							.getRemoteUser();
		}
		return userId;
	}

	public void setUserId(String userId) {
		this.userId = userId;
	}

	public Example getCurrentExample() {
		Locale current = FacesContext.getCurrentInstance().getViewRoot()
				.getLocale();
		String exampleName = (String) FacesContext.getCurrentInstance()
				.getExternalContext().getRequestParameterMap().get(
						"exampleName");
		if (exampleName == null && currentExampleShortName != null) {
			ObjectWithTags<Example> objectWithTags = getAllExamplesMapByShortName()
					.get(currentExampleShortName);
			if (objectWithTags != null) {
				return objectWithTags.getObject();
			}
		}

		if (exampleName == null) {
			exampleName = "OutputText.jspx";
		}

		if (!getAllExamplesMapByShortName().containsKey(exampleName)) {
			// no such example?
			exampleName = "OutputText.jspx"; // this one sure must be!
		}

		ObjectWithTags<Example> objectWithTags = getAllExamplesMapByShortName()
				.get(exampleName);
		if (currentExampleShortName != null && !currentExampleShortName.equals(exampleName)) {
			getCssTools().reset();
		}
		currentExampleShortName = exampleName;
		//
		return objectWithTags.getObject();
	}

	public CSSTools getCssTools() {
		if (cssTools == null) {
			cssTools = new CSSTools();
		}
		
		return cssTools;
	}

	public LinkedHashMap<String, Object> getCurrentExampleHierarhy() {
		if (currentExampleHierarhy == null) {
			ExamplesInfoLoader examplesInfoLoader = new ExamplesInfoLoader();
			visitAllExamples("/componentsUsageExamples", examplesInfoLoader);
			System.out.println("" + examplesInfoLoader.getAllExamples());

			CollectionSorter<Example> sorter = new CollectionSorter<Example>();

			LinkedHashMap<String, Object> sortedByDefault = sorter
					.sortDefault(examplesInfoLoader.getAllExamples());
			currentExampleHierarhy = sortedByDefault;

			// keep examples in map for further usage
			allExamplesMapByShortName = new LinkedHashMap<String, ObjectWithTags<Example>>();
			for (ObjectWithTags<Example> exampleWithTags : examplesInfoLoader
					.getAllExamples()) {
				allExamplesMapByShortName.put(exampleWithTags.getObject()
						.getShortName(), exampleWithTags);
			}
		}
		return currentExampleHierarhy;
	}

	public LinkedHashMap<String, ObjectWithTags<Example>> getAllExamplesMapByShortName() {
		if (allExamplesMapByShortName == null) {
			getCurrentExampleHierarhy();
		}
		return allExamplesMapByShortName;
	}

	public void visitAllExamples(String path, IResourseVisitor resourseVisitor) {
		Set paths = FacesContext.getCurrentInstance().getExternalContext()
				.getResourcePaths(path);

		if (paths == null || paths.size() == 0) {
			resourseVisitor.actionOnResource(path);
		}
		for (Object pathO : paths) {
			String subpath = (String) pathO;
			visitAllExamples(subpath, resourseVisitor);
		}
	}

	public List<MenuItem> createFromMap(LinkedHashMap<String, Object> map) {
		List<MenuItem> res = new ArrayList<MenuItem>();
		Set<String> keys = map.keySet();
		for (String key : keys) {
			MenuItem menuItem = new MenuItem();
			menuItem.setValue(key);

			Object value = map.get(key);
			if (value instanceof LinkedHashMap) {
				List<MenuItem> subList = createFromMap((LinkedHashMap<String, Object>) value);
				menuItem.getChildren().addAll(subList);
			} else {
				ObjectWithTags<Example> exampleWithTags = (ObjectWithTags<Example>) value;
				menuItem.setLink(exampleWithTags.getName());
			}
			res.add(menuItem);
		}
		return res;
	}

	public List<String> getTopLevelCategories() {
		List<String> res = new ArrayList<String>();
		res.addAll(getCurrentExampleHierarhy().keySet());

		return res;
	}

	public DefaultMutableTreeNode createNodeFromMap(
			LinkedHashMap<String, Object> map) {
		DefaultMutableTreeNode treeNode = new DefaultMutableTreeNode();
		treeNode.setAllowsChildren(true);
		for (String key : map.keySet()) {
			Object o = map.get(key);
			System.out.println("key:" + key + " o:" + o);
			if (o instanceof LinkedHashMap) {
				LinkedHashMap<String, Object> subMap = (LinkedHashMap<String, Object>) o;
				DefaultMutableTreeNode branchNode = createNodeFromMap(subMap);
				IceUserObject iceObject = new IceUserObject(branchNode);

				iceObject.setText(key);
				branchNode.setUserObject(iceObject);

				treeNode.add(branchNode);
			}
			if (o instanceof ObjectWithTags) {
				ObjectWithTags<Example> exampleWithTags = (ObjectWithTags<Example>) o;
				DefaultMutableTreeNode branchNode = new DefaultMutableTreeNode();
				IceUserObjectWithData<ObjectWithTags<Example>> iceObject = new IceUserObjectWithData<ObjectWithTags<Example>>(
						branchNode);
				branchNode.setAllowsChildren(false);
				iceObject.setData(exampleWithTags);
				branchNode.setUserObject(iceObject);
				iceObject.setText(null);
				iceObject.setLeaf(true);
				iceObject.setTooltip(exampleWithTags.getObject().getPath());
				treeNode.add(branchNode);
			}
		}
		return treeNode;
	}

	public DefaultTreeModel createTree(LinkedHashMap<String, Object> subMap) {
		DefaultMutableTreeNode rootTreeNode = createNodeFromMap(subMap);
		IceUserObject rootObject = new IceUserObject(rootTreeNode);
		rootObject.setText("Root Node");
		rootObject.setExpanded(true);
		rootTreeNode.setUserObject(rootObject);

		// model is accessed by by the ice:tree component via a getter method
		DefaultTreeModel model = new DefaultTreeModel(rootTreeNode);

		return model;
	}

	public Map<String, DefaultTreeModel> getTopCategoriesTrees() {
		if (topCategoriesTrees == null) {
			topCategoriesTrees = new LinkedHashMap<String, DefaultTreeModel>();

			Set<String> topCategories = getCurrentExampleHierarhy().keySet();
			for (String topCategory : topCategories) {
				Object o = getCurrentExampleHierarhy().get(topCategory);
				if (o instanceof LinkedHashMap) {
					LinkedHashMap<String, Object> subMap = (LinkedHashMap<String, Object>) o;

					DefaultTreeModel subTree = createTree(subMap);

					topCategoriesTrees.put(topCategory, subTree);
				}
			}
		}
		return topCategoriesTrees;
	}

	public void navigationEvent(ActionEvent event)
			throws AbortProcessingException {
		System.out.println("navigationEvent!" + event);
		// get id of node that was clicked on.
		String exampleName = ""
				+ FacesContext.getCurrentInstance().getExternalContext()
						.getRequestParameterMap().get("exampleName");
		System.out.println("exampleName=" + exampleName);

	}

	public List<MenuItem> getExamplesExploderMenuModel() {
		ExamplesInfoLoader examplesInfoLoader = new ExamplesInfoLoader();
		visitAllExamples("/componentsUsageExamples", examplesInfoLoader);
		System.out.println("" + examplesInfoLoader.getAllExamples());

		CollectionSorter<Example> sorter = new CollectionSorter<Example>();

		LinkedHashMap<String, Object> sortedByDefault = sorter
				.sortDefault(examplesInfoLoader.getAllExamples());
		System.out.println("sorted" + sortedByDefault);

		if (examplesExploderMenuModel == null) {
			examplesExploderMenuModel = createFromMap(sortedByDefault);

		}

		if (examplesExploderMenuModel == null) {
			examplesExploderMenuModel = new ArrayList<MenuItem>();
			MenuItem example1 = new MenuItem();
			example1.setValue("example1");
			example1.addActionListener(new ActionListener() {

				@Override
				public void processAction(ActionEvent arg0)
						throws AbortProcessingException {
					System.out.println("here!!");

				}
			});

			MenuItem example2 = new MenuItem();
			example2.setValue("example2");
			example2
					.setLink("componentsUsageExamples/outputText/ExampleOfOutputTextSeparated.jspx");
			MenuItem example3 = new MenuItem();
			// topLevel3.setIcon("xmlhttp/css/xp/css-images/menuitem.gif");
			example3.setValue("examplel3");

			examplesExploderMenuModel.add(example1);
			examplesExploderMenuModel.add(example2);
			examplesExploderMenuModel.add(example3);
		}

		return examplesExploderMenuModel;
	}

	public List<MenuItem> getTopMenuModel() {
		if (topMenuModel == null) {
			topMenuModel = new ArrayList<MenuItem>();
			MenuItem topLevel1 = new MenuItem();
			// topLevel1.setIcon("xmlhttp/css/xp/css-images/menuitem.gif");
			topLevel1.setValue("See");

			MenuItem topLevel2 = new MenuItem();
			// topLevel2.setIcon("xmlhttp/css/xp/css-images/menuitem.gif");
			topLevel2.setValue("Customize");

			MenuItem topLevel3 = new MenuItem();
			// topLevel3.setIcon("xmlhttp/css/xp/css-images/menuitem.gif");
			topLevel3.setValue("Present");

			topMenuModel.add(topLevel1);
			topMenuModel.add(topLevel2);
			topMenuModel.add(topLevel3);
		}
		return topMenuModel;
	}

	public void exampleSelected(ActionEvent event) {

		// get from the context content include path to show as well
		// as the title associated with the link.
		FacesContext context = FacesContext.getCurrentInstance();
		Map map = context.getExternalContext().getRequestParameterMap();
		String selectedExampleName = (String) map.get("exampleName");
	}
}
